package com.pat.java.base.nio;

import java.io.*;
import java.net.*;
import java.nio.*;
import java.util.*;
import java.nio.channels.*;
import java.nio.charset.*;

public class ClientNBlock {
	public static void main(String args[]) {
		String host = "127.0.0.1";
		SocketChannel channel = null;
		 Selector sele = null;
		try {
			//初始化
			InetSocketAddress sockAddr = new InetSocketAddress(host, 12000);
			Charset charset = Charset.forName("UTF-8");
			CharsetDecoder decoder = charset.newDecoder();
			CharsetEncoder encoder = charset.newEncoder();
			//分配缓存
			ByteBuffer buf = ByteBuffer.allocateDirect(1024);
			CharBuffer cbuf = CharBuffer.allocate(1024);
			//连接
			channel = SocketChannel.open();
			channel.configureBlocking(false);
			channel.connect(sockAddr);

			//打开选择器
			sele = Selector.open();
			//注册通道、事件
			channel.register(sele,SelectionKey.OP_CONNECT);
			
			// Wait for something of interest to happen
			System.out.println("Client startup.");
			while (sele.select()>0) {
				//得到键值组
				Set<?> readyKeys = sele.selectedKeys();
				Iterator<?> readyItor = readyKeys.iterator();
				//遍历键值组
				while (readyItor.hasNext()) {
					//得到键值
					SelectionKey k = (SelectionKey) readyItor.next();
					// Remove current entry
					readyItor.remove();
					
					//如果键值为可连接的
					if (k.isConnectable()) {
						//得到注册通道
						SocketChannel keyChannel = (SocketChannel) k.channel();
						//完成连接
						if (keyChannel.isConnectionPending()) {
							keyChannel.finishConnect();
						}
						//发送请求
						System.out.println("Client send request.");
						keyChannel.write(encoder.encode(CharBuffer.wrap("Hello.Server?")));
						
						channel.register(sele, SelectionKey.OP_READ);
					//如果键值为可读的
					} else if (k.isReadable()) {
						//得到注册通道
						SocketChannel keyChannel = (SocketChannel) k.channel();
						//读取数据
						keyChannel.read(buf);
						buf.flip();
						//解码
						decoder.decode(buf, cbuf, false);
						//显示
						cbuf.flip();
						System.out.println("Client receive message from Server:"+cbuf.toString());
						//清除缓存
						buf.clear();
						cbuf.clear();
						keyChannel.close();
					} else {
						System.err.println("Ooops");
					}
				}
			}
		} catch (UnknownHostException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		} finally {
			if (channel != null)
			{
				try {
					sele.close();
					channel.close();
				} catch (IOException e) {
					e.printStackTrace();
				}
			}
		}
	}
}